home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i092: Program identifier database tools, Part04/07
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: b8a0c027 3f0a9f92 de21f474 5deb2873
-
- Submitted-by: Tom Horsley <tom@hcx2.ssd.csd.harris.com>
- Posting-number: Volume 24, Issue 92
- Archive-name: mkid2/part04
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 4 (of 7)."
- # Contents: TUTORIAL iid.y scan-c.c
- # Wrapped by tom@hcx2 on Tue Feb 26 10:03:04 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'TUTORIAL' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'TUTORIAL'\"
- else
- echo shar: Extracting \"'TUTORIAL'\" \(16037 characters\)
- sed "s/^X//" >'TUTORIAL' <<'END_OF_FILE'
- X
- XThis is a program identifier database package. These tools provide a
- Xlogical extension to ctags. (which is limited in that it only stores the
- Xlocation of function and type *definitions*a) The ID facility
- Xstores the locations for all uses of identifiers, pre-processor
- Xnames, and numbers. (in decimal, octal or hex)
- X
- XWhen fixing or enhancing a large program (particularly one that is
- Xunfamiliar) it is often necessary to audit the use of global
- Xdata-structures in order to verify that the proposed modification will
- Xnot trigger any hidden `gotchas'. Often this entails grepping through
- Xmany thousands of lines of source code spread over dozens and sometimes
- Xhundreds of source files in multiple sub-directories. This process
- Xplaces a significant load on computing resources, and takes a long
- Xtime. There is even the danger that a programmer will avoid doing a
- Xcomplete audit due to the perceived cost--he or she will rely on memory
- Xand hope that there are no booby traps.
- X
- XThe id-database is most useful for maintaining large programs that
- Xconsist of many source files. The database is simply a two dimensional
- Xboolean array indexed by identifier-name and source-file-name. For a
- Xgiven identifier and source-file, if the identifier occurs in the file,
- Xthe boolean value is TRUE. The database may be queried either by
- Xidentifier-name or file-name.
- X
- XThe following types of queries supported:
- X
- X* name lookup
- X list all the files where an identifier occurs. The name
- X may be a regular expression.
- X
- X* name apropos
- X list all the files for all identifiers that have the sub-string
- X name in them. Matches are done in a case-insensitive mammer.
- X
- X* name `grep'
- X search for an identifier in all the files where it occurs.
- X This is an optimized `grep' over all the sources--we only
- X search on files that contain the identifier.
- X
- X* name edit
- X invoke an editor on the files where an identifier occurs,
- X and use the identifier as an initial search string.
- X
- X* file lookup
- X list all identifiers that occur in a file, or list
- X the identifiers that are common between two files.
- X
- X* non-unique names
- X list the names of all indentifiers whose names are non-unique
- X within some number of characters. This is useful when porting
- X a program from a `flexnames' system to one more limited names.
- X
- X* solo
- X list all identifiers that occur exactly once in a software
- X system. This may be useful for locating identifiers that are
- X declared but never used, or library functions that are used
- X but never declared.
- X
- X
- XThe first four queries are handled by one program. The type of query
- Xis determined by the name the program was invoked with. The four links
- Xare lid(1) for `lookup id', aid(1) for `apropos id', gid(1) for `grep
- Xid' and eid(1) for `edit id'. One or more identifiers may be passed on
- Xthe command line. The identifiers may be literal strings or regular
- Xexpressions. Here are some examples:
- X
- X$ lid FILE
- XFILE extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
- X
- X$ lid FILE$
- XAF_FILE mkid.c
- XAF_IDFILE mkid.c
- XFILE extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
- XIDFILE id.h {fid,lid,mkid}.c
- XIdFILE {fid,lid}.c
- XargFILE mkid.c
- XgidFILE lid.c
- XidFILE {init,mkid}.c
- XinFILE {gets0,getsFF,scan-asm,scan-c}.c
- XopenSrcFILE extern.h {idx,mkid,opensrc}.c
- XsrcFILE {idx,mkid,opensrc}.c
- X
- X$ lid ^get
- Xget opensrc.c
- XgetAdaId getscan.c
- XgetAsmId extern.h {getscan,scan-asm}.c
- XgetCId extern.h {getscan,scan-c}.c
- XgetDirToName extern.h {fid,lid,paths}.c
- XgetId {idx,mkid}.c
- XgetLanguage extern.h {getscan,idx,mkid}.c
- XgetLispId getscan.c
- XgetPascalId getscan.c
- XgetRoffId getscan.c
- XgetSCCS extern.h opensrc.c
- XgetScanner extern.h {getscan,idx,mkid}.c
- XgetTeXId getscan.c
- XgetTextId getscan.c
- Xgetc {gets0,getsFF,lid,scan-asm,scan-c}.c
- Xgetchar lid.c
- Xgetenv extern.h lid.c
- Xgets lid.c
- XgetsFF extern.h {bitsvec,fid,getsFF,lid,mkid}.c
- X
- XAs you can see, when a regular expression is used, it is possible to
- Xget more than one line of output. If you wish multiple lines to be
- Xmerged into one, supply the `-m' option:
- X
- X$ lid -m ^get
- X^get extern.h {bitsvec,fid,gets0,getsFF,getscan,idx,lid,mkid,opensrc,paths,scan-asm,scan-c}.c
- X
- XThe query program searches for numbers numerically rather than
- Xtextually. Therefore you may search for multiple representations of a
- Xnumber. It is best to illustrate this with examples:
- X
- X$ lid -a 0x10
- X020 numtst.c
- X0x00010 numtst.c
- X0x0010 scan-c.c
- X0x10 {id,radix}.h {scan-asm,stoi}.c
- X16 numtst.c
- X
- XThe `-a' argument tells lid(1) to look for 0x10 in all radixes. (For
- Xnumbers 0 through 7, lid(1) looks for all radixes by default. For numbers
- Xgreater than 7, lid(1) only looks for the radix that the argument is
- Xsupplied in.) It is also possible to restrict the search to selected
- Xradixes by supplying an argument consisting of one or more of the
- Xkey-letters `o', `d', and `x' for octal decimal and hexadecimal
- Xrespectively:
- X
- X$ lid -o 0x10
- X020 numtst.c
- X
- X$ lid -x 16
- X0x00010 numtst.c
- X0x0010 scan-c.c
- X0x10 {id,radix}.h {scan-asm,stoi}.c
- X
- X$ lid -d 020
- X16 numtst.c
- X
- X
- XThe grep interface behaves somewhat like the following command:
- X
- X$ grep -w -n `lid TRUE`
- X
- XHeres some sample output for the equivalent gid command:
- X
- X$ gid TRUE
- Xbool.h:5: #define TRUE (0==0)
- Xlid.c:102: case 'm': forceMerge = TRUE; break;
- Xlid.c:170: Merging = TRUE;
- Xlid.c:204: crunching = TRUE;
- Xlid.c:553: hitDigits = TRUE;
- Xlid.c:787: return TRUE;
- Xmkid.c:117: Verbose = TRUE;
- Xmkid.c:191: keepLang = TRUE;
- Xscan-asm.c:79: static bool eatUnder = TRUE;
- Xscan-asm.c:80: static bool preProcess = TRUE;
- Xscan-asm.c:96: static bool newLine = TRUE;
- Xscan-asm.c:130: newLine = TRUE;
- Xscan-asm.c:141: newLine = TRUE;
- Xscan-asm.c:145: newLine = TRUE;
- Xscan-asm.c:150: newLine = TRUE;
- Xscan-asm.c:165: newLine = TRUE;
- Xscan-c.c:88: static bool eatUnder = TRUE;
- Xscan-c.c:101: static bool newLine = TRUE;
- Xscan-c.c:138: newLine = TRUE;
- Xscan-c.c:199: newLine = TRUE;
- Xscan-c.c:205: newLine = TRUE;
- Xscan-c.c:210: newLine = TRUE;
- Xwmatch.c:37: return TRUE;
- X
- XNotice that each line is reported in the same format as a
- XC-preprocessor error message. This feature allows gid(1) lines to be
- Xdigested by any program that parses error messages, such as error(1)
- Xand gnu-emacs.
- X
- XIf you want to edit all files that have an identifier, you may
- Xconveniently do so with eid(1):
- X
- X$ eid TRUE
- XTRUE bool.h {lid,mkid,scan-asm,scan-c,wmatch}.c
- XEdit? [y1-9^S/nq]
- X
- XBefore the editor is invoked, you are given the lid(1) output to review
- Xand comfirm. If you want to edit all files listed, respond with a
- Xnewline or with `y'. If you want to skip some number of files into the
- Xargument list, respond with a single digit `1' through `9' to skip that
- Xmany files, or do a string-search to the first file you want with
- X`^S<string>' or `/<string>'. If you don't want to edit anything, type
- X`n' to go on to the next argument you gave to eid(1) or type `q' to
- Xquit altogether.
- X
- XThe behavior of the editing interface is controlled by three
- Xenvironment variables called EIDARG, EIDLDEL, and EIDRDEL. The best
- Xway to illustrate their use by an example. Here is how to define them
- Xfor vi(1) (using /bin/sh syntax)
- X
- XEIDARG='+/%s/' # printf(3) string for initial search-string argument
- XEIDLDEL='\<' # left word-delimiter
- XEIDRDEL='\>' # right word-delimiter
- X
- X`EID[LR]DEL' are positioned around the identifier as left and right
- Xword-delimiters if your editor supports that notion. Then the whole
- Xname-string is sprintf(3)'ed into `EIDARG' to construct the initial
- Xsearch-string argument to the editor. If your editor can't digest such
- Xan argument, simply leave these variables undefined in the
- Xenvironment.
- X
- XSome emacs users are appalled at the notion of starting up a fresh editor
- Xsimply to follow an identifier. For those who are fortunate enough to have
- Xa programmable emacs such as gnu-emacs, it is fairly simple to devise
- Xa command that invokes gid(1) and digests its output as though it were
- X/lib/cpp error strings to be examined. (Sorry, no such code is provided
- Xat this posting...)
- X
- XAnother type of query is to find all identifiers that are non-unique
- Xwithin some number of characters. This is useful for finding potential
- Xportability problems when moving to a system whose compiler or linker
- Xlimits the number of significant characters in a name. The `-u<n>'
- Xargument does the trick. Here's a list of identifiers that may yield
- Xmultiply-defined errors in a symbol table that only knows about the
- Xfirst 7 characters:
- X
- X$ lid -u7
- XSCAN_TEX getscan.c
- XSCAN_TEXT getscan.c
- Xidh_argc id.h {init,mkid}.c
- Xidh_argo id.h {init,mkid}.c
- Xidh_namc id.h {fid,mkid}.c
- Xidh_namo id.h {fid,init,lid,mkid}.c
- XoldHashSize mkid.c
- XoldHashTable mkid.c
- X
- XBetter yet, if you want to edit these, try
- X
- X$ eid -u7
- X^SCAN_TE getscan.c
- XEdit? [y1-9^S/nq] n
- X^idh_arg getscan.c id.h {init,mkid}.c
- XEdit? [y1-9^S/nq] n
- X^idh_nam {fid,getscan}.c id.h {init,lid,mkid}.c
- XEdit? [y1-9^S/nq] n
- X^oldHash {fid,getscan}.c id.h {init,lid,mkid}.c
- XEdit? [y1-9^S/nq] n
- X
- X
- XAn additional feature of lid(1) is that pathnames are automatically
- Xadjusted for the current working directory. Large programs such as the
- XUNIX kernel are often partitioned into subsystems whose sources live in
- Xdifferent directories. What follows are several examples of the same
- Xsearch conducted from different points in the UNIX kernel source
- Xhierarchy:
- X
- X$ cd /src/uts/m68k
- X$ lid bdevsw
- Xbdevsw sys/conf.h cf/conf.c io/bio.c os/{fio,main,prf,sys3}.c
- X
- X$ cd io
- X$ lid bdevsw
- Xbdevsw ../sys/conf.h ../cf/conf.c bio.c ../os/{fio,main,prf,sys3}.c
- X
- X$ cd ../os
- Xbdevsw ../sys/conf.h ../cf/conf.c ../io/bio.c {fio,main,prf,sys3}.c
- X
- XThe database is built with mkid(1). The user supplies pathnames
- Xeither on the command line or on stdin. Here's the output of the
- X`verbose' option to mkid(1):
- X
- X$ mkid -v *.h *.c
- Xc: bitops.h
- Xc: bool.h
- Xc: extern.h
- Xc: id.h
- Xc: patchlevel.h
- Xc: radix.h
- Xc: string.h
- Xc: basename.c
- Xc: bitcount.c
- Xc: bitops.c
- Xc: bitsvec.c
- Xc: bsearch.c
- Xc: bzero.c
- Xc: document.c
- Xc: fid.c
- Xc: gets0.c
- Xc: getsFF.c
- Xc: getscan.c
- Xc: hash.c
- Xc: idx.c
- Xc: init.c
- Xc: lid.c
- Xc: mkid.c
- Xc: numtst.c
- Xc: opensrc.c
- Xc: paths.c
- Xc: scan-asm.c
- Xc: scan-c.c
- Xc: stoi.c
- Xc: tty.c
- Xc: uerror.c
- Xc: wmatch.c
- XCompressing Hash Table...
- XSorting Hash Table...
- XWriting `ID'...
- XNames: 593, Numbers: 64, Strings: 43, Solo: 119, Total: 697
- XOccurrances: 11.67, Load: 0.17, Probes: 1.07
- X
- XMkid(1) echoes the name of each file as it is scanned, prefixed by the
- Xname of the language it thinks the file is written in. Mkid(1) reports
- Xhow many unique names and numbers were found, how many names occurred
- Xonly once, and the total for names and numbers. It also reports the
- Xaverage number of occurrances for all names and numbers. Next, there
- Xare some hash-table statistics on the load-factor and the average
- Xnumber of open-addressed probes.
- X
- XMkid(1) can take arguments from the command line, from stdin, or from
- Xa file. A file full of filenames may also contain mkid options of the form
- X-<option>. Filenames and options appear in the file one-per-line. Typical
- Xusage for this feature is as follows:
- X
- X$ find . -name '*.[chys]' -print >IDFILES
- X$ mkid -aIDFILES
- X
- X-- or --
- X
- X$ find . -name '*.[chys]' -print |mkid -
- X
- XMkid(1) stashes the filenames and relevant arguments in the database
- Xitself. It uses these to support the ``incremental-update' option.
- XIf invoked with `-u', mkid(1) checks the modification times of all
- Xconstituent files, and only re-scans those that are newer than the
- Xdatabase itself. It is invoked like so:
- X
- X$ mkid -u
- X
- XIn summation, mkid(1) can get arguments from one of four places:
- X1) the command line, 2) a file, 3) stdin, 4) the database itself.
- X
- XMkid(1) accepts a number of scanner-specific arguments. Generally,
- Xthese are introduced with `-S<lang>' where <lang> is the name of
- Xa language, such as `c' or `asm'. You can get a scanner-specific
- Xusage-report with `-S<lang>?' (Of course, the `?' must be escaped
- Xto get it past the shell)
- X
- XHere's scanner-usage for the assembly language scanner:
- X
- X$ mkid -Sasm\?
- XThe Assembler scanner arguments take the form -Sasm<arg>, where
- X<arg> is one of the following: (<cc> denotes one or more characters)
- X -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.
- X (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.
- X (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.
- X (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.
- X (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)
- X
- X`-Sasm-c<cc>' tells the scanner what characters are used to introduce comments
- Xthat extend to end-of-line.
- X
- XUse `-Sasm+u' if your C compiler prepends leading underscores to external
- Xnames. This way, mkid(1) will strip leading underscores, and the name
- X`foo' in a C source will be correctly associated with the name `_foo'
- Xin an assembler source. If your compiler doesn't prepend leading
- Xunderscores, use `-Sasm-u'.
- X
- XMany assemblers allow special characters to be mixed with
- Xalpha-numerics in label, constant and register names. Common choices
- Xare `.', `%', and `$'. Thus, a label such as `L%123' should be scanned
- Xas one token, not broken up into the name `L' and the number 123.
- X`-Sasm-a%.' tells the scanner to allow `%' and `.' in tokens, but to throw
- Xaway tokens containing `%' or `.' `-Sasm+a%.' tells the scanner to keep such
- Xtokens and put them into the database.
- X
- X
- X`-Sasm+p' tells the scanner to handle `#include' and `#define' lines as
- Xin C source, and `-Sasm+C' tells it to ignore C-style comments.
- X
- XHere's the scanner-usage for C:
- X
- X$ mkid -Sc\?
- XThe C scanner arguments take the form -Sc<arg>, where <arg>
- Xis one of the following: (<cc> denotes one or more characters)
- X (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.
- X -s<cc> . . . . Allow <cc> in string ids.
- X
- XThe `+u' argument is akin to the argument for the assembly-language
- Xscanner. Mkid(1) keeps the contents of quoted-strings if the string
- Xcontains a single valid C name and nothing else. E.g. mkid(1) would
- Xkeep the contents of "_proc". Such strings are interesting because
- Xthey may contain symbol names that a program uses for nlist lookups.
- XSo, if your compiler prepends underscores to external symbols, use
- X`-Sc+u' so that mkid(1) will strip them back off.
- X
- XMkid(1) normally throws away the contents of quoted strings that have
- Xanything other than a single name in them. You can tell mkid(1) to
- Xaccept additional characters in strings with `-Sc-s<cc>' where <cc> is
- Xone or more special characters. E.g. `-Sc-s/.-:,' will include most of
- Xthe strings containing pathnames that you are likely to encounter.
- X
- XAnother class of scanner argument allows you to associate a suffix
- Xwith a language. E.g. `-S.y=c' tells mkid(1) to use the C language
- Xscanner on all files ending with .y. You can ask mkid(1) for the
- Xavailable scanners and associated suffixes like so:
- X
- X$ mkid -S\?=\?
- X.c=c, .h=c, .y=c, .s=asm, .p=pascal, .pas=pascal
- X
- XPlease note, mkid(1) is lying to you about its Pascal prowess!
- XAt the time of this posting, there are scanners for C and assembly
- Xlanguage sources. There are also stubs for Pascal, Ada and LISP. The
- Xscanners are very fast. The assembly language scanner knows how
- Xto throw away C-style comments as well as the traditional `comment-
- Xcharacter-until-end-of-line' style. In order to test new scanners,
- Xthere is a scanner driver called idx(1). Idx(1) simply calls the
- Xscanner to get identifiers one-at-a-time prints them on stdout one-per-line.
- X
- XFor more information, read the manual pages!
- X
- XHappy Hacking,
- X--
- X-- Greg McGary
- X-- P.O. Box 286
- X-- Lincoln, MA 01773
- X--
- X-- 9/15/87
- X--
- X-- Until the end of 1987,
- X-- Consulting to Sun's East Coast Division:
- X-- gmcgary@ecd.sun.com
- X-- gmcgary@suneast.uu.net
- X--
- X-- After that, probably consulting in Europe...
- END_OF_FILE
- if test 16037 -ne `wc -c <'TUTORIAL'`; then
- echo shar: \"'TUTORIAL'\" unpacked with wrong size!
- fi
- # end of 'TUTORIAL'
- fi
- if test -f 'iid.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'iid.y'\"
- else
- echo shar: Extracting \"'iid.y'\" \(11278 characters\)
- sed "s/^X//" >'iid.y' <<'END_OF_FILE'
- X%{
- X/* This is the yacc definition for the iid command language.
- X * The main program, scanner, and parser are defined here.
- X * The utility functions invoked from here are in iidfun.c
- X */
- X
- X#include "iiddef.h"
- X
- X%}
- X
- X%union {
- X set_type * setdef ;
- X id_type * strdef ;
- X id_list_type * listdef ;
- X}
- X
- X%token < setdef > SET
- X
- X%token < strdef > ID SHELL_QUERY SHELL_COMMAND
- X
- X%type < setdef > Query Primitive
- X
- X%type < listdef > Lid_group Aid_group Id_list Command_list
- X
- X%token LID AID BEGIN SETS SS FILES SHOW HELP OFF MATCH
- X
- X%left OR
- X
- X%left AND
- X
- X%left NOT
- X
- X%start Command
- X
- X%%
- X
- XCommand :
- X BEGIN ID
- X {
- X /* cd to the directory specified as argument, flush sets */
- X
- X SetDirectory($2) ;
- X FlushSets() ;
- X }
- X| Set_query Query
- X| File_query Query
- X {
- X /* print the list of files resulting from Query */
- X
- X PrintSet($2) ;
- X }
- X| SHOW SET
- X {
- X /* run PAGER on the list of files in SET */
- X
- X RunPager(Pager, $2) ;
- X }
- X| SETS
- X {
- X /* describe sets created so far */
- X
- X DescribeSets() ;
- X }
- X| HELP
- X {
- X /* run PAGER on the help file */
- X
- X RunPager(Pager, HelpSet) ;
- X }
- X| OFF
- X {
- X exit(0) ;
- X }
- X| SHELL_QUERY Command_list
- X {
- X /* run the shell command and eat the results as a file set */
- X
- X OneDescription(RunProg($1->id, $2)) ;
- X free($1) ;
- X }
- X| SHELL_COMMAND Command_list
- X {
- X /* run the shell command */
- X
- X RunShell($1->id, $2) ;
- X free($1) ;
- X }
- X;
- X
- XSet_query :
- X SS
- X {
- X /* Turn on verbose query flag */
- X
- X VerboseQuery = TRUE ;
- X }
- X;
- X
- XFile_query :
- X FILES
- X {
- X /* Turn off verbose query flag */
- X
- X VerboseQuery = FALSE ;
- X }
- X;
- X
- XQuery :
- X Primitive
- X {
- X /* value of query is set associated with primitive */
- X
- X $$ = $1 ;
- X }
- X| Query AND Query
- X {
- X /* value of query is intersection of the two query sets */
- X
- X $$ = SetIntersect($1, $3) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X| Query OR Query
- X {
- X /* value of query is union of the two query sets */
- X
- X $$ = SetUnion($1, $3) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X| NOT Query
- X {
- X /* value of query is inverse of other query */
- X
- X $$ = SetInverse($2) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X;
- X
- XPrimitive :
- X SET
- X {
- X /* Value of primitive is value of recorded set */
- X
- X $$ = $1 ;
- X }
- X| Lid_group
- X {
- X /* Value of primitive is obtained by running an lid query */
- X
- X $$ = RunProg(LidCommand, $1) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X| Aid_group
- X {
- X /* Value of primitive is obtained by running an aid query */
- X
- X $$ = RunProg("aid -kmn", $1) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X| MATCH Id_list
- X {
- X /* Match names from database against pattern */
- X $$ = RunProg("pid -kmn", $2) ;
- X if (VerboseQuery) {
- X OneDescription($$) ;
- X }
- X }
- X| '(' Query ')'
- X {
- X /* value of primitive is value of query */
- X
- X $$ = $2 ;
- X }
- X;
- X
- XLid_group :
- X ID
- X {
- X /* make arg list holding single ID */
- X
- X $$ = InitList() ;
- X $$ = ExtendList($$, $1) ;
- X LidCommand = DefaultCommand ;
- X }
- X| LID Id_list
- X {
- X /* arg list is Id_list */
- X
- X $$ = $2 ;
- X LidCommand = "lid -kmn" ;
- X }
- X;
- X
- XAid_group :
- X AID Id_list
- X {
- X /* arg list is Id_list */
- X
- X $$ = $2 ;
- X }
- X;
- X
- XCommand_list :
- X ID
- X {
- X /* make arg list holding single ID */
- X
- X $$ = InitList() ;
- X $$ = ExtendList($$, $1) ;
- X }
- X| SET
- X {
- X /* make arg list holding names from set */
- X
- X $$ = InitList() ;
- X $$ = SetList($$, $1) ;
- X }
- X| Command_list ID
- X {
- X /* extend arg list with additional ID */
- X
- X $$ = ExtendList($1, $2) ;
- X }
- X| Command_list SET
- X {
- X /* extend arg list with additional file names */
- X
- X $$ = SetList($1, $2) ;
- X }
- X;
- X
- XId_list :
- X ID
- X {
- X /* make arg list holding single ID */
- X
- X $$ = InitList() ;
- X $$ = ExtendList($$, $1) ;
- X }
- X| Id_list ID
- X {
- X /* extend arg list with additional ID */
- X
- X $$ = ExtendList($1, $2) ;
- X }
- X;
- X
- X%%
- X
- X/* ScanLine - a global variable holding a pointer to the current
- X * command being scanned.
- X */
- Xchar * ScanLine ;
- X
- X/* ScanPtr - a global pointer to the current scan position in ScanLine.
- X */
- Xchar * ScanPtr ;
- X
- X/* yytext - buffer holding the token.
- X */
- Xchar yytext [ MAXCMD ] ;
- X
- X/* yyerror - process syntax errors.
- X */
- Xint
- Xyyerror(s)
- X char * s ;
- X{
- X if (*ScanPtr == '\0') {
- X fprintf(stderr,"Syntax error near end of command.\n") ;
- X } else {
- X fprintf(stderr,"Syntax error on or before %s\n",ScanPtr) ;
- X }
- X return(0) ;
- X}
- X
- X/* ScanInit - initialize the yylex routine for the new line of input.
- X * Basically just initializes the global variables that hold the char
- X * ptrs the scanner uses.
- X */
- Xvoid
- XScanInit(line)
- X char * line ;
- X{
- X /* skip the leading white space - the yylex routine is sensitive
- X * to keywords in the first position on the command line.
- X */
- X
- X while (isspace(*line)) ++line ;
- X ScanLine = line ;
- X ScanPtr = line ;
- X}
- X
- X/* NameEq - compare two names for equality in a case insensitive manner.
- X * return TRUE for equal, FALSE otherwise.
- X */
- Xint
- XNameEq(n1,n2)
- X char * n1 ;
- X char * n2 ;
- X{
- X char c1 ;
- X char c2 ;
- X
- X for ( ; ; ) {
- X c1 = *n1++ ;
- X c2 = *n2++ ;
- X if (isalpha(c1)) c1 = tolower(c1) ;
- X if (isalpha(c2)) c2 = tolower(c2) ;
- X if (c1 != c2) return FALSE ;
- X if (c1 == '\0') return TRUE ;
- X }
- X}
- X
- X/* yylex - the scanner for iid. Basically a kludge ad-hoc piece of junk,
- X * but what the heck, if it works...
- X *
- X * Mostly just scans for non white space strings and returns ID for them.
- X * Does check especially for '(' and ')'. Just before returning ID it
- X * checks for command names if it is the first token on line or
- X * AND, OR, LID, AID if it is in the middle of a line.
- X */
- Xint
- Xyylex()
- X{
- X char * bp ;
- X char c ;
- X int code = ID ;
- X char * dp ;
- X char * sp ;
- X int val ;
- X
- X bp = ScanPtr ;
- X while (isspace(*bp)) ++bp ;
- X sp = bp ;
- X c = *sp++ ;
- X if ((c == '(') || (c == ')') || (c == '\0')) {
- X ScanPtr = sp ;
- X if (c == '\0') {
- X --ScanPtr ;
- X }
- X return(c) ;
- X } else {
- X dp = yytext ;
- X while (! ((c == '(') || (c == ')') || (c == '\0') || isspace(c))) {
- X *dp++ = c ;
- X c = *sp++ ;
- X }
- X *dp++ = '\0' ;
- X ScanPtr = sp - 1 ;
- X if (bp == ScanLine) {
- X
- X /* first token on line, check for command names */
- X
- X if (NameEq(yytext, "SS")) return(SS) ;
- X if (NameEq(yytext, "FILES")) return(FILES) ;
- X if (NameEq(yytext, "F")) return(FILES) ;
- X if (NameEq(yytext, "HELP")) return(HELP) ;
- X if (NameEq(yytext, "H")) return(HELP) ;
- X if (NameEq(yytext, "?")) return(HELP) ;
- X if (NameEq(yytext, "BEGIN")) return(BEGIN) ;
- X if (NameEq(yytext, "B")) return(BEGIN) ;
- X if (NameEq(yytext, "SETS")) return(SETS) ;
- X if (NameEq(yytext, "SHOW")) return(SHOW) ;
- X if (NameEq(yytext, "P")) return(SHOW) ;
- X if (NameEq(yytext, "OFF")) return(OFF) ;
- X if (NameEq(yytext, "Q")) return(OFF) ;
- X if (NameEq(yytext, "QUIT")) return(OFF) ;
- X if (yytext[0] == '!') {
- X code = SHELL_COMMAND ;
- X } else {
- X code = SHELL_QUERY ;
- X }
- X } else {
- X
- X /* not first token, check for operator names */
- X
- X if (NameEq(yytext, "LID")) return(LID) ;
- X if (NameEq(yytext, "AID")) return(AID) ;
- X if (NameEq(yytext, "AND")) return(AND) ;
- X if (NameEq(yytext, "OR")) return(OR) ;
- X if (NameEq(yytext, "NOT")) return(NOT) ;
- X if (NameEq(yytext, "MATCH")) return(MATCH) ;
- X if ((yytext[0] == 's' || yytext[0] == 'S') && isdigit(yytext[1])) {
- X
- X /* this might be a set specification */
- X
- X sp = &yytext[1] ;
- X val = 0 ;
- X for ( ; ; ) {
- X c = *sp++ ;
- X if (c == '\0') {
- X if (val < NextSetNum) {
- X yylval.setdef = TheSets[val] ;
- X return(SET) ;
- X }
- X }
- X if (isdigit(c)) {
- X val = (val * 10) + (c - '0') ;
- X } else {
- X break ;
- X }
- X }
- X }
- X }
- X yylval.strdef = (id_type *)malloc(sizeof(id_type) + strlen(yytext)) ;
- X if (yylval.strdef == NULL) {
- X fatal("Out of memory in yylex") ;
- X }
- X yylval.strdef->next_id = NULL ;
- X if (code == SHELL_COMMAND) {
- X strcpy(yylval.strdef->id, &yytext[1]) ;
- X } else {
- X strcpy(yylval.strdef->id, yytext) ;
- X }
- X return(code) ;
- X }
- X}
- X
- X/* The main program for iid - parse the command line, initialize processing,
- X * loop processing one command at a time.
- X */
- Xmain(argc, argv)
- X int argc ;
- X char * argv [ ] ;
- X{
- X int c ; /* current option */
- X char * CmdPtr ; /* Points to the command string */
- X char Command [ MAXCMD ] ; /* Buffer for reading commands */
- X int Do1 = FALSE ; /* TRUE if should only do 1 command */
- X int DoPrompt ; /* TRUE if should write a prompt */
- X int errors = 0 ; /* error count */
- X
- X DoPrompt = isatty(fileno(stdin)) ;
- X while ((c = getopt(argc, argv, "Hac:")) != EOF) {
- X switch(c) {
- X case 'a':
- X DefaultCommand = "aid -kmn" ;
- X break ;
- X case 'c':
- X CmdPtr = optarg ;
- X Do1 = TRUE ;
- X break ;
- X case 'H':
- X fputs("\
- Xiid: interactive ID database query tool. Call with:\n\
- X iid [-a] [-c] [-H]\n\
- X\n\
- X-a\tUse the aid as the default query command (not lid).\n\
- X-c cmd\tExecute the single query cmd and exit.\n\
- X-H\tPrint this message and exit.\n\
- X\n\
- XTo get help after starting program type 'help'.\n\
- X",stderr) ;
- X exit(0) ;
- X default:
- X ++errors ;
- X break ;
- X }
- X }
- X if (argc != optind) {
- X fputs("iid: Excess arguments ignored.\n",stderr) ;
- X ++errors ;
- X }
- X if (errors) {
- X fputs("run iid -H for help.\n",stderr) ;
- X exit(1) ;
- X }
- X
- X /* initialize global data */
- X
- X InitIid() ;
- X
- X /* run the parser */
- X
- X if (Do1) {
- X ScanInit(CmdPtr) ;
- X exit(yyparse()) ;
- X } else {
- X for ( ; ; ) {
- X if (DoPrompt) {
- X fputs(Prompt, stdout) ;
- X fflush(stdout) ;
- X }
- X gets(Command) ;
- X if (feof(stdin)) {
- X if (DoPrompt) fputs("\n", stdout) ;
- X strcpy(Command, "off") ;
- X }
- X ScanInit(Command) ;
- X errors += yyparse() ;
- X }
- X }
- X}
- END_OF_FILE
- if test 11278 -ne `wc -c <'iid.y'`; then
- echo shar: \"'iid.y'\" unpacked with wrong size!
- fi
- # end of 'iid.y'
- fi
- if test -f 'scan-c.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'scan-c.c'\"
- else
- echo shar: Extracting \"'scan-c.c'\" \(8401 characters\)
- sed "s/^X//" >'scan-c.c' <<'END_OF_FILE'
- X/* Copyright (c) 1986, Greg McGary */
- X/* Vhil scanning mods added Jan 7th, 1988 by Tom Horsley */
- Xstatic char sccsid[] = "@(#)scan-c.c 1.1 86/10/09";
- X
- X#include <bool.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <id.h>
- X
- Xchar *getCId();
- Xchar *getVhilId();
- Xvoid setCArgs();
- X
- Xstatic void clrCtype();
- Xstatic void setCtype();
- X
- X#define I1 0x0001 /* 1st char of an identifier [a-zA-Z_] */
- X#define DG 0x0002 /* decimal digit [0-9] */
- X#define NM 0x0004 /* extra chars in a hex or long number [a-fA-FxXlL] */
- X#define C1 0x0008 /* C comment introduction char: / */
- X#define C2 0x0010 /* C comment termination char: * */
- X#define Q1 0x0020 /* single quote: ' */
- X#define Q2 0x0040 /* double quote: " */
- X#define ES 0x0080 /* escape char: \ */
- X#define NL 0x0100 /* newline: \n */
- X#define EF 0x0200 /* EOF */
- X#define SK 0x0400 /* Make these chars valid for names within strings */
- X#define VH 0x0800 /* VHIL comment introduction char: # */
- X#define WS 0x1000 /* White space characters */
- X
- X/*
- X character class membership macros:
- X*/
- X#define ISDIGIT(c) ((rct)[c]&(DG)) /* digit */
- X#define ISNUMBER(c) ((rct)[c]&(DG|NM)) /* legal in a number */
- X#define ISEOF(c) ((rct)[c]&(EF)) /* EOF */
- X#define ISID1ST(c) ((rct)[c]&(I1)) /* 1st char of an identifier */
- X#define ISIDREST(c) ((rct)[c]&(I1|DG)) /* rest of an identifier */
- X#define ISSTRKEEP(c) ((rct)[c]&(I1|DG|SK)) /* keep contents of string */
- X#define ISSPACE(c) ((rct)[c]&(WS)) /* white space character */
- X/*
- X The `BORING' classes should be skipped over
- X until something interesting comes along...
- X*/
- X#define ISBORING(c) (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1|VH))) /* fluff */
- X#define ISCBORING(c) (!((rct)[c]&(EF|C2))) /* comment fluff */
- X#define ISVBORING(c) (!((rct)[c]&(EF|NL))) /* vhil comment fluff */
- X#define ISQ1BORING(c) (!((rct)[c]&(EF|NL|Q1|ES))) /* char const fluff */
- X#define ISQ2BORING(c) (!((rct)[c]&(EF|NL|Q2|ES))) /* quoted str fluff */
- X
- Xstatic short idctype[] = {
- X
- X EF,
- X
- X /* 0 1 2 3 4 5 6 7 */
- X /* ----- ----- ----- ----- ----- ----- ----- ----- */
- X
- X /*000*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*010*/ 0, 0, NL, 0, 0, 0, 0, 0,
- X /*020*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*030*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*040*/ 0, 0, Q2, 0, 0, 0, 0, Q1,
- X /*050*/ 0, 0, C2, 0, 0, 0, 0, C1,
- X /*060*/ DG, DG, DG, DG, DG, DG, DG, DG,
- X /*070*/ DG, DG, 0, 0, 0, 0, 0, 0,
- X /*100*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
- X /*110*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
- X /*120*/ I1, I1, I1, I1, I1, I1, I1, I1,
- X /*130*/ I1|NM, I1, I1, 0, ES, 0, 0, I1,
- X /*140*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
- X /*150*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
- X /*160*/ I1, I1, I1, I1, I1, I1, I1, I1,
- X /*170*/ I1|NM, I1, I1, 0, 0, 0, 0, 0,
- X
- X /*200*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*210*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*220*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*230*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*240*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*250*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*260*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*270*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*300*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*310*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*320*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*330*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*340*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*350*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*360*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X /*370*/ 0, 0, 0, 0, 0, 0, 0, 0,
- X
- X};
- X
- Xstatic bool eatUnder = TRUE;
- Xstatic bool scanVhil = FALSE;
- X
- X/*
- X*/
- Xchar *
- XgetVhilId(inFILE, flagP)
- X{
- X if (! scanVhil) {
- X setCArgs("vhil",'+',"v");
- X }
- X return(getCId(inFILE, flagP));
- X}
- X
- X/*
- X Grab the next identifier the C source
- X file opened with the handle `inFILE'.
- X This state machine is built for speed, not elegance.
- X*/
- Xchar *
- XgetCId(inFILE, flagP)
- X FILE *inFILE;
- X int *flagP;
- X{
- X static char idBuf[BUFSIZ];
- X static bool newLine = TRUE;
- X register short *rct = &idctype[1];
- X register int c;
- X register char *id = idBuf;
- X
- Xtop:
- X c = getc(inFILE);
- X if (newLine) {
- X newLine = FALSE;
- X if (c == '.') {
- X /* Auto-recognize vhil code when you see a . in column 1.
- X * also ignore lines that start with a .
- X */
- X if (! scanVhil) {
- X setCArgs("vhil",'+',"v");
- X }
- X while (ISVBORING(c))
- X c = getc(inFILE);
- X newLine = TRUE;
- X goto top;
- X }
- X if (c != '#')
- X goto next;
- X c = getc(inFILE);
- X if (scanVhil && ISSPACE(c)) {
- X while (ISVBORING(c))
- X c = getc(inFILE);
- X newLine = TRUE;
- X goto top;
- X }
- X while (ISBORING(c))
- X c = getc(inFILE);
- X if (!ISID1ST(c))
- X goto next;
- X id = idBuf;
- X *id++ = c;
- X while (ISIDREST(c = getc(inFILE)))
- X *id++ = c;
- X *id = '\0';
- X if (strequ(idBuf, "include")) {
- X while (c == ' ' || c == '\t') c = getc(inFILE) ;
- X if (c == '\n') {newLine = TRUE; goto top;}
- X id = idBuf;
- X if (c == '"') {
- X c = getc(inFILE);
- X while (c != '\n' && c != EOF && c != '"') {
- X *id++ = c;
- X c = getc(inFILE);
- X }
- X *flagP = IDN_STRING;
- X } else if (c == '<') {
- X c = getc(inFILE);
- X while (c != '\n' && c != EOF && c != '>') {
- X *id++ = c;
- X c = getc(inFILE);
- X }
- X *flagP = IDN_STRING;
- X } else if (ISID1ST(c)) {
- X *id++ = c ;
- X while (ISIDREST(c = getc(inFILE))) *id++ = c;
- X *flagP = IDN_NAME;
- X } else {
- X while (c != '\n' && c != EOF) c = getc(inFILE);
- X newLine = TRUE;
- X goto top;
- X }
- X while (c != '\n' && c != EOF) c = getc(inFILE) ;
- X newLine = TRUE;
- X *id = '\0';
- X return idBuf;
- X }
- X if (strnequ(idBuf, "if", 2)
- X || strequ(idBuf, "define")
- X || strequ(idBuf, "elif") /* ansi C */
- X || (scanVhil && strequ(idBuf, "elsif"))
- X || strequ(idBuf, "undef"))
- X goto next;
- X while ((c != '\n') && (c != EOF))
- X c = getc(inFILE);
- X newLine = TRUE;
- X goto top;
- X }
- X
- Xnext:
- X while (ISBORING(c))
- X c = getc(inFILE);
- X
- X switch (c)
- X {
- X case '"':
- X id = idBuf;
- X *id++ = c = getc(inFILE);
- X for (;;) {
- X while (ISQ2BORING(c))
- X *id++ = c = getc(inFILE);
- X if (c == '\\') {
- X *id++ = c = getc(inFILE);
- X continue;
- X } else if (c != '"')
- X goto next;
- X break;
- X }
- X *--id = '\0';
- X id = idBuf;
- X while (ISSTRKEEP(*id))
- X id++;
- X if (*id || id == idBuf) {
- X c = getc(inFILE);
- X goto next;
- X }
- X *flagP = IDN_STRING;
- X if (eatUnder && idBuf[0] == '_' && idBuf[1])
- X return &idBuf[1];
- X else
- X return idBuf;
- X
- X case '\'':
- X c = getc(inFILE);
- X for (;;) {
- X while (ISQ1BORING(c))
- X c = getc(inFILE);
- X if (c == '\\') {
- X c = getc(inFILE);
- X continue;
- X } else if (c == '\'')
- X c = getc(inFILE);
- X goto next;
- X }
- X
- X case '/':
- X if ((c = getc(inFILE)) != '*')
- X goto next;
- X c = getc(inFILE);
- X for (;;) {
- X while (ISCBORING(c))
- X c = getc(inFILE);
- X if ((c = getc(inFILE)) == '/') {
- X c = getc(inFILE);
- X goto next;
- X } else if (ISEOF(c)) {
- X newLine = TRUE;
- X return NULL;
- X }
- X }
- X
- X case '\n':
- X newLine = TRUE;
- X goto top;
- X
- X case '#':
- X if (! scanVhil) {
- X /* Auto-recognize vhil when find a # in the middle of a line.
- X */
- X setCArgs("vhil",'+',"v");
- X }
- X c = getc(inFILE);
- X while (ISVBORING(c))
- X c = getc(inFILE);
- X newLine = TRUE;
- X goto top;
- X default:
- X if (ISEOF(c)) {
- X newLine = TRUE;
- X return NULL;
- X }
- X name:
- X id = idBuf;
- X *id++ = c;
- X if (ISID1ST(c)) {
- X *flagP = IDN_NAME;
- X while (ISIDREST(c = getc(inFILE)))
- X *id++ = c;
- X } else if (ISDIGIT(c)) {
- X *flagP = IDN_NUMBER;
- X while (ISNUMBER(c = getc(inFILE)))
- X *id++ = c;
- X } else
- X fprintf(stderr, "junk: `\\%3o'", c);
- X ungetc(c, inFILE);
- X *id = '\0';
- X *flagP |= IDN_LITERAL;
- X return idBuf;
- X }
- X}
- X
- Xstatic void
- XsetCtype(chars, type)
- X char *chars;
- X int type;
- X{
- X short *rct = &idctype[1];
- X
- X while (*chars)
- X rct[*chars++] |= type;
- X}
- Xstatic void
- XclrCtype(chars, type)
- X char *chars;
- X int type;
- X{
- X short *rct = &idctype[1];
- X
- X while (*chars)
- X rct[*chars++] &= ~type;
- X}
- X
- Xextern char *MyName;
- Xstatic void
- Xusage(lang)
- X char *lang;
- X{
- X fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
- X exit(1);
- X}
- Xstatic char *cDocument[] =
- X{
- X"The C scanner arguments take the form -Sc<arg>, where <arg>",
- X"is one of the following: (<cc> denotes one or more characters)",
- X" (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
- X" -s<cc> . . . . Allow <cc> in string ids.",
- X" -v . . . . . . Skip vhil comments.",
- XNULL
- X};
- Xvoid
- XsetCArgs(lang, op, arg)
- X char *lang;
- X int op;
- X char *arg;
- X{
- X if (op == '?') {
- X document(cDocument);
- X return;
- X }
- X switch (*arg++)
- X {
- X case 'u':
- X eatUnder = (op == '+');
- X break;
- X case 's':
- X setCtype(arg, SK);
- X break;
- X case 'v':
- X setCtype("$", I1);
- X setCtype("#", VH);
- X setCtype(" \t", WS);
- X scanVhil = TRUE;
- X break;
- X default:
- X if (lang)
- X usage(lang);
- X break;
- X }
- X}
- END_OF_FILE
- if test 8401 -ne `wc -c <'scan-c.c'`; then
- echo shar: \"'scan-c.c'\" unpacked with wrong size!
- fi
- # end of 'scan-c.c'
- fi
- echo shar: End of archive 4 \(of 7\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 7 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- exit 0 # Just in case...
-